package com.ewzj.bigdata.app.config

import android.app.Activity
import android.app.Application
import android.content.Context
import android.net.ParseException
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.text.TextUtils
import com.antfortune.freeline.FreelineCore
import com.baidu.mapapi.SDKInitializer
import com.ewzj.bigdata.BuildConfig
import com.ewzj.bigdata.R
import com.ewzj.bigdata.app.config.netmodel.Api
import com.ewzj.bigdata.app.config.netmodel.CommonCache
import com.ewzj.bigdata.app.config.netmodel.CommonService
import com.ewzj.bigdata.app.utils.HttpsUtils
import com.ewzj.bigdata.mvp.model.rspbean.CityBean
import com.ewzj.bigdata.mvp.ui.activity.AboutActivity
import com.ewzj.bigdata.mvp.ui.activity.LogoActivity
import com.ewzj.bigdata.mvp.ui.activity.MainTabActivity
import com.google.gson.JsonIOException
import com.google.gson.JsonParseException
import com.gyf.barlibrary.ImmersionBar
import com.jess.arms.base.App
import com.jess.arms.base.BaseApplication
import com.jess.arms.base.delegate.AppDelegate
import com.jess.arms.di.module.GlobalConfigModule
import com.jess.arms.http.GlobalHttpHandler
import com.jess.arms.http.RequestInterceptor
import com.jess.arms.integration.ConfigModule
import com.jess.arms.integration.IRepositoryManager
import com.jess.arms.utils.DataHelper
import com.jess.arms.utils.DeviceUtils
import com.jess.arms.utils.UiUtils
import com.mcxiaoke.packer.helper.PackerNg
import com.sina.weibo.sdk.api.share.Base
import com.squareup.leakcanary.LeakCanary
import com.squareup.leakcanary.RefWatcher
import com.tinkerpatch.sdk.TinkerPatch
import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike
import com.umeng.analytics.AnalyticsConfig
import com.umeng.analytics.MobclickAgent
import com.umeng.analytics.game.UMGameAgent
import com.umeng.socialize.Config
import com.umeng.socialize.PlatformConfig
import com.umeng.socialize.UMShareAPI
import com.umeng.socialize.UMShareConfig
import com.umeng.socialize.utils.ContextUtil
import io.reactivex.exceptions.CompositeException
import io.rx_cache2.RxCacheException
import me.iwf.photopicker.PhotoPickerActivity
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import org.json.JSONException
import org.json.JSONObject
import retrofit2.HttpException
import timber.log.Timber
import java.io.InputStream
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeUnit


/**
 * author:zhangjing
 * 作用:
 * return:
 */
open public class GlobalConfituration : ConfigModule {
    override fun applyOptions(context: Context, builder: GlobalConfigModule.Builder) {
        builder.baseurl(Api.APP_DOMAIN).globalHttpHandler(object : GlobalHttpHandler {
            override fun onHttpRequestBefore(chain: Interceptor.Chain, request: Request): Request {
                //如果需要再请求服务器之前做一些操作,则重新返回一个做过操作的的requeat如增加header,不做操作则返回request
                val apitoken = DataHelper.getStringSF(context, AppKey.API_TOKEN)
                val channelid = DataHelper.getStringSF(context, AppKey.BAIDU_CHANNELID)
                val mGson=((context.applicationContext) as BaseApplication).appComponent.gson()
                var locationcity=DataHelper.getStringSF(context,AppKey.LOCATION_CITY)
                var cityId="63"
                if (!locationcity.isNullOrEmpty()){
                    var citybean=mGson.fromJson(locationcity,CityBean.ListEntity::class.java)
                    cityId=citybean.id
                }
                val newRequest = chain.request().newBuilder().header("Authorization", if (TextUtils.isEmpty(apitoken)) "" else "Bearer " + apitoken)
                        .header("City-Id", cityId)
                        .header("Channel-Id", channelid?: "")
                        .header("and_version",DeviceUtils.getVersionName(context))
                        .header("Model", android.os.Build.MODEL + "," + android.os.Build.VERSION.SDK)
                        .build()
                return newRequest
            }

            override fun onHttpResultResponse(httpResult: String?, chain: Interceptor.Chain?, response: Response): Response {
                try {
                    if (!TextUtils.isEmpty(httpResult) && RequestInterceptor.isJson(response.body()!!)) {
                        val json = JSONObject(httpResult)
                        val code = json.getInt("code")
                        if (code != AppKey.API_SUCCESS) {
                            val msg = json.getString("msg")
                            throw ApiException(code, msg)
                        }

                    }

                } catch (e: JSONException) {
                    e.printStackTrace()
                    return response
                }

                return response
            }

        }).responseErroListener { context, e ->
            run {
                Timber.tag("Catch-Error").w(e.message)
                var msg = "未知错误"
                if (e is UnknownHostException) {
                    msg = "网络不可用"
                } else if (e is SocketTimeoutException) {
                    msg = "请求网络超时"
                } else if (e is HttpException) {
                    msg = convertStatusCode(e)
                } else if (e is JsonParseException || e is ParseException || e is JSONException || e is JsonIOException) {
                    msg = "数据解析错误"
                } else if (e is ApiException) {
                    msg = e.message.toString()
                } else if (e is RxCacheException) {
                    msg = "缓存读取失败"
                }else if (e is CompositeException){
                    msg = "数据读取失败，请稍后重试"
                }
                UiUtils.SnackbarText(msg)
            }
        }.gsonConfiguration { context, builder ->
            builder.disableHtmlEscaping().enableComplexMapKeySerialization()//支持将序列化key为object的map,默认只能序列化key为string的map
        }.retrofitConfiguration { context, builder ->
            //这里可以自己自定义配置Retrofit的参数,甚至你可以替换系统配置好的okhttp对象
            //retrofitBuilder.addConverterFactory(FastJsonConverterFactory.create());//比如使用fastjson替代gson
        }.okhttpConfiguration { context, builder ->
            val sslParams = provideSSL(context);
            builder.writeTimeout(30, TimeUnit.SECONDS).sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                    .hostnameVerifier { hostname, session -> return@hostnameVerifier true }

        }.rxCacheConfiguration { context, builder ->
            //这里可以自己自定义配置RxCache的参数
            builder.useExpiredDataIfLoaderNotAvailable(true)
        }

    }

    override fun injectAppLifecycle(context: Context, lifecycles: MutableList<AppDelegate.Lifecycle>) {
        lifecycles.add(object : AppDelegate.Lifecycle {
            override fun onTerminate(application: Application?) {

            }
            override fun onCreate(application: Application?) {
                ContextUtil.setContext(application)
                Config.DEBUG=BuildConfig.LOG_DEBUG
                UMGameAgent.setDebugMode(Config.DEBUG)
                var market = PackerNg.getMarket(application)
                MobclickAgent.enableEncrypt(false)

                MobclickAgent.startWithConfigure(MobclickAgent.UMAnalyticsConfig(application, AppKey.UMENG_KEY, market,MobclickAgent.EScenarioType.E_UM_NORMAL))
                // DEX分包
                FreelineCore.init(application)
                //友盟分享
                PlatformConfig.setWeixin("wx3e531f7fb435acba", "835325458118b36d214dcbe5b30abbcc")
                PlatformConfig.setQQZone("101387766", "adfc28f90aa0c26ce64aa2459181eaf1")
                PlatformConfig.setSinaWeibo("3376425558", "09e18c5a0b4331d7bea847aaf99eb9b1", "http://api.15miwo.cn")
//                UMShareAPI.get(application)
                // 百度地图
                SDKInitializer.initialize(application)
                val config = UMShareConfig()
                config.isNeedAuthOnGetUserInfo=false
                config.isOpenShareEditActivity(true)
                config.setSinaAuthType(UMShareConfig.AUTH_TYPE_SSO)
                // 或者使用 PackerNg.getMarket(Context,defaultValue) 之后就可以使用了，比如友盟可以这样设置
                if (BuildConfig.LOG_DEBUG) {
                    Config.DEBUG=true
                    Timber.plant(Timber.DebugTree())
                }
//                (application as App).appComponent.extras().put(RefWatcher::class.java!!.getName(), if (BuildConfig.USE_CANARY) LeakCanary.install(application) else RefWatcher.DISABLED)
                (application as App).appComponent.extras().put(RefWatcher::class.java!!.getName(), RefWatcher.DISABLED)

            }

        })
    }

    override fun injectActivityLifecycle(context: Context?, lifecycles: MutableList<Application.ActivityLifecycleCallbacks>?) {
        lifecycles!!.add(object : Application.ActivityLifecycleCallbacks {
            private var mImmersionBar: ImmersionBar? = null
            override fun onActivityPaused(activity: Activity?) {
                MobclickAgent.onPause(activity)
            }

            override fun onActivityResumed(activity: Activity?) {
                MobclickAgent.onResume(activity)
            }

            override fun onActivityStarted(activity: Activity?) {

            }

            override fun onActivityDestroyed(activity: Activity?) {
                mImmersionBar!!.destroy()
            }

            override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {

            }

            override fun onActivityStopped(activity: Activity?) {

            }

            override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
                //这里全局给Activity设置toolbar和title,你想象力有多丰富,这里就有多强大,以前放到BaseActivity的操作都可以放到这里
                mImmersionBar= ImmersionBar.with(activity)
                if (activity is MainTabActivity){
                    mImmersionBar!!.reset().navigationBarEnable(false).statusBarDarkFont(true, 0.2f).init()
                }else if (activity is LogoActivity){
                    mImmersionBar!!.reset().init()
                }else if(activity is AboutActivity){
                    mImmersionBar!!.reset().navigationBarEnable(false).statusBarDarkFont(false).statusBarColor(R.color.maingreen)
                            .fitsSystemWindows(true).init()
                }else if (activity is PhotoPickerActivity){
                    mImmersionBar!!.reset().navigationBarEnable(false).statusBarDarkFont(false).statusBarColor(R.color.background_material_dark)
                            .fitsSystemWindows(true).init()
                }else{
                    mImmersionBar!!.reset().navigationBarEnable(false).statusBarDarkFont(true, 0.2f).statusBarColor(R.color.colorPrimary)
                            .keyboardEnable(true)
                            .fitsSystemWindows(true).init()
                }

            }
        })
    }

    override fun registerComponents(context: Context?, repositoryManager: IRepositoryManager) {
        repositoryManager.injectRetrofitService(CommonService::class.java)
        repositoryManager.injectCacheService(CommonCache::class.java)
    }

    override fun injectFragmentLifecycle(context: Context?, lifecycles: MutableList<FragmentManager.FragmentLifecycleCallbacks>?) {
        lifecycles!!.add(object : FragmentManager.FragmentLifecycleCallbacks() {

            override fun onFragmentCreated(fm: FragmentManager?, f: Fragment?, savedInstanceState: Bundle?) {
                // 在配置变化的时候将这个 Fragment 保存下来,在 Activity 由于配置变化重建是重复利用已经创建的Fragment。
                // https://developer.android.com/reference/android/app/Fragment.html?hl=zh-cn#setRetainInstance(boolean)
                // 在 Activity 中绑定少量的 Fragment 建议这样做,如果需要绑定较多的 Fragment 不建议设置此参数,如 ViewPager 需要展示较多 Fragment
                f!!.retainInstance = true
            }

            override fun onFragmentDestroyed(fm: FragmentManager?, f: Fragment?) {
//                ((f!!.activity.application as App).appComponent.extras()[RefWatcher::class.java.name] as RefWatcher).watch(this)
            }
        })
    }

    fun provideSSL(context: Context): HttpsUtils.SSLParams {
        var server: InputStream = context.getAssets().open("server.cer")
        var client: InputStream = context.getAssets().open("client.bks")
        val sslParams = HttpsUtils.getSslSocketFactory(arrayOf<InputStream>(server!!), client, "123456")
        return sslParams
    }

    private fun convertStatusCode(httpException: HttpException): String {
        val msg: String
        if (httpException.code() == 500) {
            msg = "服务器发生错误"
        } else if (httpException.code() == 404) {
            msg = "请求地址不存在"
        } else if (httpException.code() == 403) {
            msg = "请求被服务器拒绝"
        } else if (httpException.code() == 307) {
            msg = "请求被重定向其他页面"
        } else {
            msg = httpException.message()
        }
        return msg
    }
}